import logging

from webutils.compat import complex_json
from webutils.exceptions import InvalidResource
from webutils.logging import ContextAdapter

logger = logging.getLogger('server.manager')


class ResourceManager:
    BASE_LOGGER = None
    required_context = None

    def __init__(self, service, logger=None, log_context=None, **kwargs):
        self.service = service
        log_context = log_context or self.service.log_context
        if not logger:
            logger = ContextAdapter(self.BASE_LOGGER, log_context)
        self.logger = logger
        required_context = self.required_context or []
        for key in required_context:
            if key in kwargs:
                value = kwargs[key]
            else:
                value = getattr(self.service, key, None)
            assert value is not None, f'context {key} is expected'
            setattr(self, key, value)

    def serialize(self, raw):
        if hasattr(raw, 'encode'):
            return raw.encode()
        return raw

    def deserialize(self, raw):
        if hasattr(raw, 'decode'):
            return raw.decode()
        return raw


class BinaryMixin:
    def serialize(self, raw):
        return raw

    def deserialize(self, raw):
        return raw


class DBManager(ResourceManager):
    db = 'default'


class JsonMixin:
    def serialize(self, raw):
        return complex_json.dumps(raw)

    def deserialize(self, raw):
        try:
            return complex_json.loads(raw)
        except complex_json.JSONDecodeError as err:
            raise InvalidResource(f'failed to json_loads {err}')


class EnumMixin:
    enum_class = None

    def serialize(self, raw):
        return raw.value

    def deserialize(self, raw):
        try:
            return self.enum_class(raw)
        except ValueError as err:
            raise InvalidResource(err)
